package framework.GUI;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

import framework.automaton.Mapping;
import framework.automaton.State;
import framework.automaton.Visualization;
import framework.grid.Grid;
import framework.grid.Location;

/**
 * This concrete class defines a visual JPanel to be added to the Main Panel.
 * This JPanel will be used to display the grid containing all the objects.
 * 
 * @author Bill Ge, Alex Yoo, May Zhai
 *
 */
public class GridPanel extends JPanel{
	/** final int to represent the height/width of the gridpanel*/
	protected final static int GRIDPANEL_SIZE = 600;
	
	/** The grid that the GridPanel should currently display. */
	protected Grid grid = null;
	
	/** Stored mappings of the symbols/colors that should be used in the grid. */
	protected Mapping mapping = null;
	
	/**
	 * Constructor to set up the GridPanel with the initial grid and passed-in
	 * mapping of State and Visualizations to be used.
	 * 
	 * @param grid
	 * @param mapping
	 */
	GridPanel(Grid grid, Mapping mapping){
		this.grid = grid;
		this.mapping = mapping;
		
		this.setPreferredSize(new Dimension(0,GRIDPANEL_SIZE));
	}
	
	/**
	 * Draw all the objects onto the grid.
	 */
	public void paintComponent(Graphics g){
		super.paintComponent(g);

		//go through all the objects in the grid
		int rows = grid.getNumRows();
		int cols = grid.getNumCols();
		int xSize = GRIDPANEL_SIZE/rows;
		int ySize = GRIDPANEL_SIZE/cols;
		
		int min = Math.min(xSize, ySize);
		xSize = min;
		ySize = min;
		
		int x = 0;
		int y = 0;
		for(int i = 0; i <rows; i++){
			for(int j =0; j<cols; j++){
				State temp = grid.get(new Location(i,j));
				Visualization visual = mapping.getMapping(temp);
				x = xSize * i+MainFrame.FRAME_BORDER;
				y = ySize * j;
				// If an ImageIcon is being used, scale it and paint it.
				if(visual.useImage()){
					ImageIcon image = visual.getImage();
					ImageIcon scaledImage = scaleImage(image.getImage(),xSize,ySize);
					scaledImage.paintIcon(this, g, x, y);
				}
				// Otherwise fill a Rectangle with the appropriate Color.
				else{
					Color color = visual.getColor();
					g.setColor(color);
					g.fillRect(x, y, xSize, ySize);
				}
			}
		}
	}
	
	/**
	 * Called by paintComponent to scale the image into a new Image with the
	 * specified width and height in pixels
	 * 
	 * Code credited to 'hardwired' on the forum website:
	 * www.java-forums.org/java-2d/14407-imageicon-sized.html
	 * 
	 * @param src
	 * @param w
	 * @param h
	 * @return
	 */
	private ImageIcon scaleImage(Image src, int w, int h) {
        int type = BufferedImage.TYPE_INT_RGB;
        BufferedImage dst = new BufferedImage(w, h, type);
        Graphics2D g2 = dst.createGraphics();
        g2.drawImage(src, 0, 0, w, h, this);
        g2.dispose();
        return new ImageIcon(dst);
    }


	/**
	 * Called by the MainFrame in order to display a new grid .
	 * @param grid
	 */
	public void updateGrid(Grid newGrid){
		this.grid = newGrid;
		this.repaint();
	}
	/**
	 * 
	 * @param mapping to the visualizations to be used.
	 */
	public void updateVisualizationMapping(Mapping mapping){
		this.mapping = mapping;
	}
}
